{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import copy\n",
    "import math\n",
    "import time\n",
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "import pdb\n",
    "import pickle\n",
    "\n",
    "import torch\n",
    "import torch.nn as nn\n",
    "import torch.nn.functional as F\n",
    "from torch.autograd import Variable"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "class EncoderDecoder(nn.Module):\n",
    "    \"\"\"标准的Encoder-Decoder架构\"\"\"\n",
    "    def __init__(self, encoder, decoder, src_embed, tgt_embed, generator):\n",
    "        super(EncoderDecoder, self).__init__()\n",
    "        self.encoder = encoder\n",
    "        self.decoder = decoder\n",
    "        self.src_embed = src_embed   # 源序列embedding\n",
    "        self.tgt_embed = tgt_embed   # 目标序列embedding\n",
    "        self.generator = generator   # 生成目标单词的概率\n",
    "        \n",
    "    def forward(self, src, tgt, src_mask, tgt_mask):\n",
    "        \"接收和处理原序列,目标序列,以及他们的mask\"\n",
    "        return self.decode(self.encode(src, src_mask), src_mask,\n",
    "                            tgt, tgt_mask)\n",
    "    \n",
    "    def encode(self, src, src_mask):\n",
    "        return self.encoder(self.src_embed(src), src_mask)\n",
    "    \n",
    "    def decode(self, memory, src_mask, tgt, tgt_mask):\n",
    "        return self.decoder(self.tgt_embed(tgt), memory, src_mask, tgt_mask)\n",
    "\n",
    "\n",
    "class Generator(nn.Module):\n",
    "    \"\"\"定义标准的linear+softmax生成步骤\"\"\"\n",
    "    def __init__(self, d_model, vocab):\n",
    "        super(Generator, self).__init__()\n",
    "        self.proj = nn.Linear(d_model, vocab)\n",
    "\n",
    "    def forward(self, x):\n",
    "        return F.log_softmax(self.proj(x), dim=-1)\n",
    "\n",
    "\n",
    "# Encoder部分\n",
    "def clones(module, N):\n",
    "    \"产生N个相同的层\"\n",
    "    return nn.ModuleList([copy.deepcopy(module) for _ in range(N)])\n",
    "\n",
    "\n",
    "class Encoder(nn.Module):\n",
    "    \"\"\"N层堆叠的Encoder\"\"\"\n",
    "    def __init__(self, layer, N):\n",
    "        super(Encoder, self).__init__()\n",
    "        self.layers = clones(layer, N)\n",
    "        self.norm = LayerNorm(layer.size)\n",
    "        \n",
    "    def forward(self, x, mask):\n",
    "        \"每层layer依次通过输入序列与mask\"\n",
    "        for layer in self.layers:\n",
    "            x = layer(x, mask)\n",
    "        return self.norm(x)\n",
    "\n",
    "class LayerNorm(nn.Module):\n",
    "    \"\"\"构造一个layernorm模块\"\"\"\n",
    "    def __init__(self, features, eps=1e-6):\n",
    "        super(LayerNorm, self).__init__()\n",
    "        self.a_2 = nn.Parameter(torch.ones(features))\n",
    "        self.b_2 = nn.Parameter(torch.zeros(features))\n",
    "        self.eps = eps\n",
    "\n",
    "    def forward(self, x):\n",
    "        \"Norm\"\n",
    "        mean = x.mean(-1, keepdim=True)\n",
    "        std = x.std(-1, keepdim=True)\n",
    "        return self.a_2 * (x - mean) / (std + self.eps) + self.b_2\n",
    "\n",
    "\n",
    "class SublayerConnection(nn.Module):\n",
    "    \"\"\"Add+Norm\"\"\"\n",
    "    def __init__(self, size, dropout):\n",
    "        super(SublayerConnection, self).__init__()\n",
    "        self.norm = LayerNorm(size)\n",
    "        self.dropout = nn.Dropout(dropout)\n",
    "\n",
    "    def forward(self, x, sublayer):\n",
    "        \"add norm\"\n",
    "        return x + self.dropout(sublayer(self.norm(x)))\n",
    "\n",
    "class EncoderLayer(nn.Module):\n",
    "    \"\"\"Encoder分为两层Self-Attn和Feed Forward\"\"\"\n",
    "    def __init__(self, size, self_attn, feed_forward, dropout):\n",
    "        super(EncoderLayer, self).__init__()\n",
    "        self.self_attn = self_attn\n",
    "        self.feed_forward = feed_forward\n",
    "        self.sublayer = clones(SublayerConnection(size, dropout), 2)\n",
    "        self.size = size\n",
    "\n",
    "    def forward(self, x, mask):\n",
    "        \"Self-Attn和Feed Forward\"\n",
    "        x = self.sublayer[0](x, lambda x: self.self_attn(x, x, x, mask))\n",
    "        return self.sublayer[1](x, self.feed_forward)\n",
    "\n",
    "\n",
    "# Decoder部分\n",
    "class Decoder(nn.Module):\n",
    "    \"\"\"带mask功能的通用Decoder结构\"\"\"\n",
    "    def __init__(self, layer, N):\n",
    "        super(Decoder, self).__init__()\n",
    "        self.layers = clones(layer, N)\n",
    "        self.norm = LayerNorm(layer.size)\n",
    "        \n",
    "    def forward(self, x, memory, src_mask, tgt_mask):\n",
    "        for layer in self.layers:\n",
    "            x = layer(x, memory, src_mask, tgt_mask)\n",
    "        return self.norm(x)\n",
    "\n",
    "\n",
    "class DecoderLayer(nn.Module):\n",
    "    \"\"\"Decoder is made of self-attn, src-attn, and feed forward\"\"\"\n",
    "    def __init__(self, size, self_attn, src_attn, feed_forward, dropout):\n",
    "        super(DecoderLayer, self).__init__()\n",
    "        self.size = size\n",
    "        self.self_attn = self_attn\n",
    "        self.src_attn = src_attn\n",
    "        self.feed_forward = feed_forward\n",
    "        self.sublayer = clones(SublayerConnection(size, dropout), 3)\n",
    " \n",
    "    def forward(self, x, memory, src_mask, tgt_mask):\n",
    "        \"将decoder的三个Sublayer串联起来\"\n",
    "        m = memory\n",
    "        x = self.sublayer[0](x, lambda x: self.self_attn(x, x, x, tgt_mask))\n",
    "        x = self.sublayer[1](x, lambda x: self.src_attn(x, m, m, src_mask))\n",
    "        return self.sublayer[2](x, self.feed_forward)\n",
    "\n",
    "def subsequent_mask(size):\n",
    "    \"\"\"\n",
    "    mask后续的位置，返回[size, size]尺寸下三角Tensor\n",
    "    对角线及其左下角全是1，右上角全是0\n",
    "    \"\"\"\n",
    "    attn_shape = (1, size, size)\n",
    "    subsequent_mask = np.triu(np.ones(attn_shape), k=1).astype('uint8')\n",
    "    return torch.from_numpy(subsequent_mask) == 0\n",
    "\n",
    "\n",
    "# Attention\n",
    "def attention(query, key, value, mask=None, dropout=None):\n",
    "    \"计算Attention即点乘V\"\n",
    "    d_k = query.size(-1)\n",
    "    # [B, h, L, L]\n",
    "    scores = torch.matmul(query, key.transpose(-2, -1)) \\\n",
    "             / math.sqrt(d_k)\n",
    "    if mask is not None:\n",
    "        scores = scores.masked_fill(mask == 0, -1e9)\n",
    "    p_attn = F.softmax(scores, dim = -1)\n",
    "    if dropout is not None:\n",
    "        p_attn = dropout(p_attn)\n",
    "    return torch.matmul(p_attn, value), p_attn\n",
    "\n",
    "\n",
    "class MultiHeadedAttention(nn.Module):\n",
    "    def __init__(self, h, d_model, dropout=0.1):\n",
    "        \"Take in model size and number of heads.\"\n",
    "        super(MultiHeadedAttention, self).__init__()\n",
    "        assert d_model % h == 0\n",
    "        self.d_k = d_model // h\n",
    "        self.h = h\n",
    "        self.linears = clones(nn.Linear(d_model, d_model), 4)\n",
    "        self.attn = None\n",
    "        self.dropout = nn.Dropout(p=dropout)\n",
    "        \n",
    "    def forward(self, query, key, value, mask=None):\n",
    "        \"\"\"\n",
    "        实现MultiHeadedAttention。\n",
    "           输入的q，k，v是形状 [batch, L, d_model]。\n",
    "           输出的x 的形状同上。\n",
    "        \"\"\"\n",
    "        if mask is not None:\n",
    "            # Same mask applied to all h heads.\n",
    "            mask = mask.unsqueeze(1)\n",
    "        nbatches = query.size(0)\n",
    "        \n",
    "        # 1) 这一步qkv变化:[batch, L, d_model] ->[batch, h, L, d_model/h] \n",
    "        query, key, value = \\\n",
    "            [l(x).view(nbatches, -1, self.h, self.d_k).transpose(1, 2)\n",
    "                   for l, x in zip(self.linears, (query, key, value))]\n",
    "        \n",
    "        # 2) 计算注意力attn 得到attn*v 与attn\n",
    "        # qkv :[batch, h, L, d_model/h] -->x:[b, h, L, d_model/h], attn[b, h, L, L]\n",
    "        x, self.attn = attention(query, key, value, mask=mask, dropout=self.dropout)\n",
    "        # 3) 上一步的结果合并在一起还原成原始输入序列的形状\n",
    "        x = x.transpose(1, 2).contiguous().view(nbatches, -1, self.h * self.d_k)\n",
    "        # 最后再过一个线性层\n",
    "        return self.linears[-1](x)\n",
    "\n",
    "    \n",
    "# Position-wise Feed-Forward Networks\n",
    "class PositionwiseFeedForward(nn.Module):\n",
    "    \"实现FFN函数\"\n",
    "    def __init__(self, d_model, d_ff, dropout=0.1):\n",
    "        super(PositionwiseFeedForward, self).__init__()\n",
    "        self.w_1 = nn.Linear(d_model, d_ff)\n",
    "        self.w_2 = nn.Linear(d_ff, d_model)\n",
    "        self.dropout = nn.Dropout(dropout)\n",
    "\n",
    "    def forward(self, x):\n",
    "        return self.w_2(self.dropout(F.relu(self.w_1(x))))\n",
    "\n",
    "# Embeddings\n",
    "class Embeddings(nn.Module):\n",
    "    def __init__(self, d_model, vocab):\n",
    "        super(Embeddings, self).__init__()\n",
    "        self.lut = nn.Embedding(vocab, d_model)\n",
    "        self.d_model = d_model  #表示embedding的维度\n",
    "\n",
    "    def forward(self, x):\n",
    "        return self.lut(x) * math.sqrt(self.d_model)\n",
    "\n",
    "\n",
    "# Positional Encoding\n",
    "class PositionalEncoding(nn.Module):\n",
    "    \"实现PE功能\"\n",
    "    def __init__(self, d_model, dropout, max_len=5000):\n",
    "        super(PositionalEncoding, self).__init__()\n",
    "        self.dropout = nn.Dropout(p=dropout)\n",
    "        \n",
    "        pe = torch.zeros(max_len, d_model)\n",
    "        position = torch.arange(0., max_len).unsqueeze(1)\n",
    "        div_term = torch.exp(torch.arange(0., d_model, 2) *\n",
    "                             -(math.log(10000.0) / d_model))\n",
    "        \n",
    "        pe[:, 0::2] = torch.sin(position * div_term)    # 偶数列\n",
    "        pe[:, 1::2] = torch.cos(position * div_term)    # 奇数列\n",
    "        pe = pe.unsqueeze(0)           # [1, max_len, d_model]\n",
    "        self.register_buffer('pe', pe)\n",
    "        \n",
    "    def forward(self, x):\n",
    "        x = x + Variable(self.pe[:, :x.size(1)], requires_grad=False)\n",
    "        return self.dropout(x)\n",
    "\n",
    "\n",
    "# 定义一个接受超参数并生成完整模型的函数\n",
    "def make_model(src_vocab, tgt_vocab, N=6, d_model=512, d_ff=2048, h=8, dropout=0.1):\n",
    "    \"根据输入的超参数构建一个模型\"\n",
    "    c = copy.deepcopy\n",
    "    attn = MultiHeadedAttention(h, d_model)\n",
    "    ff = PositionwiseFeedForward(d_model, d_ff, dropout)\n",
    "    \n",
    "    position = PositionalEncoding(d_model, dropout)\n",
    "    model = EncoderDecoder(\n",
    "        Encoder(EncoderLayer(d_model, c(attn), c(ff), dropout), N),\n",
    "        Decoder(DecoderLayer(d_model, c(attn), c(attn), \n",
    "                             c(ff), dropout), N),\n",
    "        nn.Sequential(Embeddings(d_model, src_vocab), c(position)),\n",
    "        nn.Sequential(Embeddings(d_model, tgt_vocab), c(position)),\n",
    "        Generator(d_model, tgt_vocab))\n",
    "     \n",
    "    # 使用xavier初始化参数，这个很重要\n",
    "    for p in model.parameters():\n",
    "        if p.dim() > 1:\n",
    "            nn.init.xavier_uniform_(p)\n",
    "    return model"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "torch.Size([16, 50, 512])"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 测试MultiHeadedAttention的过程\n",
    "batch_size=16\n",
    "L = 50         # 序列长度\n",
    "d_model = 512  # 词向量维度\n",
    "h = 8\n",
    "x = torch.randn(batch_size, L, d_model)  # 生层一个测试序列x\n",
    "x.size()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "torch.Size([2, 8, 10, 64]) torch.Size([2, 8, 64, 10])\n",
      "d_k: 64\n",
      "soc: torch.Size([2, 8, 10, 10])\n",
      "attn size:  torch.Size([2, 8, 10, 10])\n",
      "torch.Size([2, 8, 10, 64])\n",
      "torch.Size([2, 10, 512])\n"
     ]
    }
   ],
   "source": [
    "# 测试MultiHeadedAttention的过程\n",
    "obj = MultiHeadedAttention(8, 512)\n",
    "q = torch.randn(2,10, 512)  # 序列输入x\n",
    "line_net = clones(nn.Linear(512, 512), 4)\n",
    "\n",
    "q, k, v = [l(x).view(2, -1, 8, 64).transpose(1,2) for l,x in zip(line_net, (q, q, q))]\n",
    "print(k.size(), k.transpose(-2, -1).size())\n",
    "d_k = d_model//h\n",
    "print(\"d_k:\", d_k)\n",
    "scores = torch.matmul(q, k.transpose(-2, -1)) / math.sqrt(d_k)\n",
    "print(\"soc:\", scores.size())\n",
    "attn = F.softmax(scores, dim = -1)\n",
    "print(\"attn size: \", attn.size())\n",
    "r_x = torch.matmul(attn, v)\n",
    "print(r_x.size())\n",
    "\n",
    "out = r_x.transpose(1, 2).contiguous().view(2, -1, 8 * 64)\n",
    "print(out.size())  # [2, 10, 512]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "# obj.forward(x,x,x,mask=None)\n",
    "# X是一个序列，X的Embedding + posEmbedding 输入Encoder，这个输入我们称为 X_emb_pos\n",
    "# Encoder有6个子结构串行，第一个的输出结果，作为第二个的输入，以此类推得到最后一个子结构的输出。\n",
    "# 第一个子结构接受输入X_emb_pos 后，按照维度平均拆分成8个，比如如果X_emb_pos的维度是512 ，拆分后的维度就是512/8=64维。\n",
    "# 这8个tensor 分别做self-attention，这个部分是8个一起并行的 ，然后得到8个结果再合并在一起，进行Norm ，norm之后再输入FFN，之后再经过norm之后输入下一个子结构。\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matplotlib.legend.Legend at 0x7f5ab293c9b0>"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 1080x360 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "# 在位置编码下方，将基于位置添加正弦波。对于每个维度，波的频率和偏移都不同。\n",
    "plt.figure(figsize=(15, 5))\n",
    "pe = PositionalEncoding(20, 0)\n",
    "y = pe.forward(Variable(torch.zeros(1, 100, 20)))\n",
    "plt.plot(np.arange(100), y[0, :, 4:8].data.numpy())\n",
    "plt.legend([\"dim %d\"%p for p in [4,5,6,7]])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## posembbeding的理解\n",
    "- 同一维度（一个单词本来有多个维度，为了可视化，选取一个维度）对比不同位置的单词在同一维度是有相对关系的，符合某个正弦或者余弦波。\n",
    "- 一个序列各个单词的位置都具有相对性。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Training 训练方案\n",
    "----\n",
    "- 定义个一个Batch对象\n",
    "- "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "class Batch(object):\n",
    "    \"定义一个训练时需要的批次数据对象，封装了用于训练的src和tgt句子，以及mask\"\n",
    "    def __init__(self, src, trg=None, pad=0):\n",
    "        self.src = src   # B 个序列[1,5,3, 0]\n",
    "        self.src_mask = (src != pad).unsqueeze(-2) # [[1,1,1,0]]\n",
    "        if trg is not None:\n",
    "            self.trg = trg[:, :-1]   # \n",
    "            self.trg_y = trg[:, 1:] # 后挪一个位置开始\n",
    "            self.trg_mask = \\\n",
    "                self.make_std_mask(self.trg, pad)\n",
    "            self.ntokens = (self.trg_y != pad).data.sum()\n",
    "    \n",
    "    @staticmethod\n",
    "    def make_std_mask(tgt, pad):\n",
    "        \"Create a mask to hide padding and future words.\"\n",
    "        tgt_mask = (tgt != pad).unsqueeze(-2)\n",
    "        tgt_mask = tgt_mask & Variable(\n",
    "            subsequent_mask(tgt.size(-1)).type_as(tgt_mask.data))\n",
    "        return tgt_mask"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 定义一个训练函数用于训练和计算损失、更新梯度"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "def run_epoch(data_iter, model, loss_compute, device):\n",
    "    \"\"\"提供训练和日志功能\"\"\"\n",
    "    start = time.time()\n",
    "    total_tokens = 0\n",
    "    total_loss = 0\n",
    "    tokens = 0\n",
    "    for i, batch in enumerate(data_iter):\n",
    "        src = batch.src.to(device)\n",
    "        trg = batch.trg.to(device)\n",
    "        src_mask = batch.src_mask.to(device)\n",
    "        trg_mask = batch.trg_mask.to(device)\n",
    "        trg_y = batch.trg_y.to(device)\n",
    "        ntokens = batch.ntokens.to(device)\n",
    "        \n",
    "        out = model.forward(src, trg, src_mask, trg_mask)\n",
    "        loss = loss_compute(out, trg_y, ntokens)\n",
    "        # 必须加上.cpu().numpy() 否则报错floating point exception (core dumped)\n",
    "        total_loss += loss.detach().cpu().numpy()\n",
    "        total_tokens += ntokens.cpu().numpy()\n",
    "        tokens += ntokens.cpu().numpy()\n",
    "        if i % 50 == 1:\n",
    "            elapsed = time.time() - start\n",
    "            print(\"Epoch Step: %d Loss: %f Tokens per Sec: %f\" %\n",
    "                    (i, loss.detach().cpu().numpy() / ntokens.cpu().numpy(), tokens / elapsed))\n",
    "            start = time.time()\n",
    "            tokens = 0\n",
    "    return total_loss / total_tokens"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 训练数据与批次\n",
    "- 使用XX数据集\n",
    "- 使用torchtext来处理数据？"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "global max_src_in_batch, max_tgt_in_batch\n",
    "def batch_size_fn(new, count, sofar):\n",
    "    \"Keep augmenting batch and calculate total number of tokens + padding.\"\n",
    "    global max_src_in_batch, max_tgt_in_batch\n",
    "    if count == 1:\n",
    "        max_src_in_batch = 0\n",
    "        max_tgt_in_batch = 0\n",
    "    max_src_in_batch = max(max_src_in_batch,  len(new.src))\n",
    "    max_tgt_in_batch = max(max_tgt_in_batch,  len(new.trg) + 2)\n",
    "    src_elements = count * max_src_in_batch\n",
    "    tgt_elements = count * max_tgt_in_batch\n",
    "    return max(src_elements, tgt_elements)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 硬件情况和时间表\n",
    "\n",
    "- 我们在一台配备8个NVIDIA P100 GPU的计算机上训练了模型。\n",
    "- 对于使用本文所述的超参数的基本模型，每个训练步骤大约需要0.4秒。\n",
    "- 我们对基本模型进行了总共100_000步或12个小时的训练。\n",
    "- 对于我们的大型模型，步长为1.0秒。大型模型接受了300,000步（3.5天）的训练。\n",
    "\n",
    "## Optimizer\n",
    "-  使用Adam优化器，其中β1= 0.9，β2= 0.98和ϵ = 10-9。\n",
    "- 根据以下公式在训练过程中改变学习率：$lrate =d_{model}^{-0.5} * min（step\\_num^{-0.5}, step\\_num * warmup\\_steps ^{-1.5}）$\n",
    "- 也就是训练步数在$warmup\\_steps内，线性增加学习率；之后的训练，按步数的负1.5平方成比例地减小学习率。我们使用了 $warmup\\_steps= 4000$。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [],
   "source": [
    "class NoamOpt(object):\n",
    "    \"Optim wrapper that implements rate.\"\n",
    "    def __init__(self, model_size, factor, warmup, optimizer):\n",
    "        self.optimizer = optimizer\n",
    "        self._step = 0\n",
    "        self.warmup = warmup\n",
    "        self.factor = factor\n",
    "        self.model_size = model_size\n",
    "        self._rate = 0\n",
    "        \n",
    "    def step(self):\n",
    "        \"Update parameters and rate\"\n",
    "        self._step += 1\n",
    "        rate = self.rate()\n",
    "        for p in self.optimizer.param_groups:\n",
    "            p['lr'] = rate\n",
    "        self._rate = rate\n",
    "        self.optimizer.step()\n",
    "        \n",
    "    def rate(self, step = None):\n",
    "        \"Implement `lrate` above\"\n",
    "        if step is None:\n",
    "            step = self._step\n",
    "        return self.factor * \\\n",
    "            (self.model_size ** (-0.5) *\n",
    "            min(step ** (-0.5), step * self.warmup ** (-1.5)))\n",
    "        \n",
    "def get_std_opt(model):\n",
    "    return NoamOpt(model.src_embed[0].d_model, 2, 4000,\n",
    "            torch.optim.Adam(model.parameters(), lr=0, betas=(0.9, 0.98), eps=1e-9))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matplotlib.legend.Legend at 0x7f5ab0133a20>"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "# 不同大小与不同超参模型的学习率曲线\n",
    "opts = [NoamOpt(512, 1, 4000, None), \n",
    "        NoamOpt(512, 1, 8000, None),\n",
    "        NoamOpt(256, 1, 4000, None)]\n",
    "plt.plot(np.arange(1, 20000), [[opt.rate(i) for opt in opts] for i in range(1, 20000)])\n",
    "plt.legend([\"512:4000\", \"512:8000\", \"256:4000\"])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 正如我们所分析，先线性增加，然后再逐渐减小。\n",
    "---\n",
    "\n",
    "## 正则化\n",
    "### 标签平滑\n",
    "- 在训练期间，我们采用ϵls = 0.1的标签平滑。随着模型训练变得更加不确定，这会增加困惑度perplexity，但会提高准确率（accuracy）和BLEU分数。\n",
    "- 使用KL div损失实现标签平滑，而不是使用one-hot目标分布，我们创建的分布具有对正确单词的置信度以及其余平滑质量分布在整个词汇表中的置信度。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [],
   "source": [
    "class LabelSmoothing(nn.Module):\n",
    "    \"实现labelsmoothing.\"\n",
    "    def __init__(self, size, padding_idx, smoothing=0.0):\n",
    "        super(LabelSmoothing, self).__init__()\n",
    "        self.criterion = nn.KLDivLoss(reduction='sum')\n",
    "        self.padding_idx = padding_idx\n",
    "        self.confidence = 1.0 - smoothing\n",
    "        self.smoothing = smoothing\n",
    "        self.size = size\n",
    "        self.true_dist = None\n",
    "        \n",
    "    def forward(self, x, target):\n",
    "        assert x.size(1) == self.size\n",
    "        true_dist = x.data.clone()\n",
    "        true_dist.fill_(self.smoothing / (self.size - 2))\n",
    "        true_dist.scatter_(1, target.data.unsqueeze(1), self.confidence)\n",
    "        true_dist[:, self.padding_idx] = 0\n",
    "        mask = torch.nonzero(target.data == self.padding_idx)\n",
    "        if mask.dim() > 0:\n",
    "            true_dist.index_fill_(0, mask.squeeze(), 0.0)\n",
    "        self.true_dist = true_dist\n",
    "        return self.criterion(x, Variable(true_dist, requires_grad=False))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 例子\n",
    "- "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matplotlib.image.AxesImage at 0x7f5ab0294c18>"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Example of label smoothing.\n",
    "crit = LabelSmoothing(5, 0, 0.4)\n",
    "predict = torch.FloatTensor([[0, 0.2, 0.7, 0.1, 0],\n",
    "                             [0, 0.2, 0.7, 0.1, 0], \n",
    "                             [0, 0.2, 0.7, 0.1, 0]])\n",
    "v = crit(Variable(predict.log()), \n",
    "         Variable(torch.LongTensor([2, 1, 0])))\n",
    "\n",
    "# Show the target distributions expected by the system.\n",
    "plt.imshow(crit.true_dist)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[<matplotlib.lines.Line2D at 0x7f5ab02ec2e8>]"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "crit = LabelSmoothing(5, 0, 0.1)\n",
    "def loss(x):\n",
    "    d = x + 3 * 1\n",
    "    predict = torch.FloatTensor([[0, x / d, 1 / d, 1 / d, 1 / d],])\n",
    "    #print(predict)\n",
    "    return crit(Variable(predict.log()), Variable(torch.LongTensor([1]))).item()\n",
    "plt.plot(np.arange(1, 100), [loss(x) for x in range(1, 100)])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 用一个小例子测试一下\n",
    "- 构造数据"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [],
   "source": [
    "## 数据生成\n",
    "def data_gen(V, batch, nbatches):\n",
    "    \"Generate random data for a src-tgt copy task.\"\n",
    "    for i in range(nbatches):\n",
    "        data = torch.from_numpy(np.random.randint(1, V, size=(batch, 10)))\n",
    "        data[:, 0] = 1\n",
    "        src = Variable(data, requires_grad=False)\n",
    "        tgt = Variable(data, requires_grad=False)\n",
    "        yield Batch(src, tgt, 0)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<generator object data_gen at 0x7f5aa03dcca8>"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "data_gen(11, 30,20)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [],
   "source": [
    "class SimpleLossCompute(object):\n",
    "    \"A simple loss compute and train function.\"\n",
    "    def __init__(self, generator, criterion, opt=None):\n",
    "        self.generator = generator\n",
    "        self.criterion = criterion\n",
    "        self.opt = opt\n",
    "\n",
    "    def __call__(self, x, y, norm):\n",
    "        x = self.generator(x)\n",
    "        loss = self.criterion(x.contiguous().view(-1, x.size(-1)),\n",
    "                              y.contiguous().view(-1)) / norm\n",
    "        loss.backward()\n",
    "        if self.opt is not None:\n",
    "            self.opt.step()\n",
    "            self.opt.optimizer.zero_grad()\n",
    "        return loss * norm.float()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 贪婪解码\n",
    "# Train the simple copy task.\n",
    "V = 11\n",
    "device = torch.device(\"cuda:0\" if torch.cuda.is_available() else \"cpu\")\n",
    "criterion = LabelSmoothing(size=V, padding_idx=0, smoothing=0.1)\n",
    "\n",
    "model = make_model(V, V, N=2)\n",
    "model = model.to(device)\n",
    "model_opt = NoamOpt(model.src_embed[0].d_model, 1, 400,\n",
    "        torch.optim.Adam(model.parameters(), lr=0, betas=(0.9, 0.98), eps=1e-9))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [],
   "source": [
    "# data = torch.rand(30,20,)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [],
   "source": [
    "# s1 = data[9]\n",
    "# print(s1.src[5], \n",
    "#       s1.trg[5], # \n",
    "#       s1.trg_y[5], \n",
    "#       s1.src_mask.size(),\n",
    "#       sep=\"\\n\")\n",
    "# print(s1.trg_mask[5])\n",
    "# print(\"ntokens\", s1.ntokens)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "tensor([[[1, 0, 0, 0, 0, 0, 0, 0],\n",
       "         [1, 1, 0, 0, 0, 0, 0, 0],\n",
       "         [1, 1, 1, 0, 0, 0, 0, 0],\n",
       "         [1, 1, 1, 1, 0, 0, 0, 0],\n",
       "         [1, 1, 1, 1, 1, 0, 0, 0],\n",
       "         [1, 1, 1, 1, 1, 1, 0, 0],\n",
       "         [1, 1, 1, 1, 1, 1, 1, 0],\n",
       "         [1, 1, 1, 1, 1, 1, 1, 1]]], dtype=torch.uint8)"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "mask = subsequent_mask(8)\n",
    "# mask = mask.unsqueeze(1)\n",
    "mask"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "torch.Size([1, 8, 8])"
      ]
     },
     "execution_count": 23,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "score = torch.randn(1,8, 8)\n",
    "score.size()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "tensor([[[-1.9573e-01, -1.0000e+09, -1.0000e+09, -1.0000e+09, -1.0000e+09,\n",
       "          -1.0000e+09, -1.0000e+09, -1.0000e+09],\n",
       "         [ 6.8826e-01,  2.0662e+00, -1.0000e+09, -1.0000e+09, -1.0000e+09,\n",
       "          -1.0000e+09, -1.0000e+09, -1.0000e+09],\n",
       "         [ 6.6923e-02,  8.2864e-01,  1.0869e+00, -1.0000e+09, -1.0000e+09,\n",
       "          -1.0000e+09, -1.0000e+09, -1.0000e+09],\n",
       "         [ 7.9477e-01,  2.0423e-01,  5.2164e-01,  7.2249e-01, -1.0000e+09,\n",
       "          -1.0000e+09, -1.0000e+09, -1.0000e+09],\n",
       "         [ 4.8070e-01, -1.5997e+00, -2.7634e-01, -1.1522e+00, -2.1877e+00,\n",
       "          -1.0000e+09, -1.0000e+09, -1.0000e+09],\n",
       "         [ 1.6565e+00, -1.3158e+00, -4.1631e-01,  3.1523e-01, -6.0585e-01,\n",
       "          -1.4173e+00, -1.0000e+09, -1.0000e+09],\n",
       "         [ 9.1306e-02, -1.9335e+00, -4.0153e-01,  5.5175e-01, -2.2587e+00,\n",
       "           6.8304e-01, -6.6239e-01, -1.0000e+09],\n",
       "         [-5.8243e-01,  1.4409e+00,  4.3986e-01,  3.7233e-01, -6.1916e-01,\n",
       "           3.8241e-01, -9.2507e-01, -5.4309e-01]]])"
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "score.masked_fill(mask == 0, -1e9)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [],
   "source": [
    "# a = (s1.trg != 0).unsqueeze(-2) & Variable(subsequent_mask(9).type_as(s1.trg_mask.data))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [],
   "source": [
    "# a.size()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch Step: 1 Loss: 2.490279 Tokens per Sec: 1354.205838\n",
      "Epoch Step: 1 Loss: 1.495896 Tokens per Sec: 6887.282458\n",
      "1.424284080222801\n",
      "Epoch Step: 1 Loss: 1.495560 Tokens per Sec: 5311.150413\n",
      "Epoch Step: 1 Loss: 1.278627 Tokens per Sec: 6867.527062\n",
      "1.2427716064453125\n",
      "Epoch Step: 1 Loss: 1.482808 Tokens per Sec: 5263.556517\n",
      "Epoch Step: 1 Loss: 1.123872 Tokens per Sec: 6872.569972\n",
      "1.104600558810764\n",
      "Epoch Step: 1 Loss: 1.792834 Tokens per Sec: 5215.222420\n",
      "Epoch Step: 1 Loss: 1.022330 Tokens per Sec: 6850.080026\n",
      "1.0013944272641782\n",
      "Epoch Step: 1 Loss: 1.010889 Tokens per Sec: 5243.292667\n",
      "Epoch Step: 1 Loss: 0.776213 Tokens per Sec: 6860.392131\n",
      "0.8232519870334202\n"
     ]
    }
   ],
   "source": [
    "for epoch in range(5):\n",
    "    model.train()\n",
    "    loss_func = SimpleLossCompute(model.generator, criterion, model_opt)\n",
    "    run_epoch(data_gen(V, 30, 20), model, loss_func, device)\n",
    "    model.eval()\n",
    "    print(run_epoch(data_gen(V, 30, 5), model, \n",
    "                  SimpleLossCompute(model.generator, criterion, None), device))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [],
   "source": [
    "# https://www.cnblogs.com/shiyublog/p/10909009.html#_label5\n",
    "# src = [\"美中两国可能很快达成一个贸易协议。\"]\n",
    "# trg = [\"The United States and China may soon reach a trade agreement.\"]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 预测\n",
    "\n",
    "- 最后的 linear layer 将 decoder 的输出扩展到与 vocabulary size 一样的维度上。经过 softmax 后，选择概率最高的一个 word 作为预测结果。\n",
    "\n",
    "- 假设我们有一个已经训练好的网络，在做预测时，步骤如下：\n",
    "\n",
    "    - 给 decoder 输入 encoder 对整个句子 embedding 的结果 和一个特殊的开始符号 </s>。decoder 将产生预测，在我们的例子中应该是 ”I”。\n",
    "    - 给 decoder 输入 encoder 的 embedding 结果和 “</s>I”，在这一步 decoder 应该产生预测 “Love”。\n",
    "    - 给 decoder 输入 encoder 的 embedding 结果和 “</s>I Love”，在这一步 decoder 应该产生预测 “China”。\n",
    "    - 给 decoder 输入 encoder 的 embedding 结果和 “</s>I Love China”, decoder应该生成句子结尾的标记，decoder 应该输出 ”</eos>”。\n",
    "然后 decoder 生成了 </eos>，翻译完成。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.9"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
